home *** CD-ROM | disk | FTP | other *** search
/ Aminet 30 / Aminet 30 (1999)(Schatztruhe)[!][Apr 1999].iso / Aminet / gfx / misc / gnuplot-3.7src.lha / gnuplot-3.7src / gnuplot-3.7.lha / gnuplot-3.7 / misc.c < prev    next >
C/C++ Source or Header  |  1998-12-10  |  39KB  |  1,506 lines

  1. #ifndef lint
  2. static char *RCSid = "$Id: misc.c,v 1.79 1998/04/14 00:16:02 drd Exp $";
  3. #endif
  4.  
  5. /* GNUPLOT - misc.c */
  6.  
  7. /*[
  8.  * Copyright 1986 - 1993, 1998   Thomas Williams, Colin Kelley
  9.  *
  10.  * Permission to use, copy, and distribute this software and its
  11.  * documentation for any purpose with or without fee is hereby granted,
  12.  * provided that the above copyright notice appear in all copies and
  13.  * that both that copyright notice and this permission notice appear
  14.  * in supporting documentation.
  15.  *
  16.  * Permission to modify the software is granted, but not the right to
  17.  * distribute the complete modified source code.  Modifications are to
  18.  * be distributed as patches to the released version.  Permission to
  19.  * distribute binaries produced by compiling modified sources is granted,
  20.  * provided you
  21.  *   1. distribute the corresponding source modifications from the
  22.  *    released version in the form of a patch file along with the binaries,
  23.  *   2. add special version identification to distinguish your version
  24.  *    in addition to the base release version number,
  25.  *   3. provide your name and address as the primary contact for the
  26.  *    support of your modified version, and
  27.  *   4. retain our contact information in regard to use of the base
  28.  *    software.
  29.  * Permission to distribute the released version of the source code along
  30.  * with corresponding source modifications in the form of a patch file is
  31.  * granted with same provisions 2 through 4 for binary distributions.
  32.  *
  33.  * This software is provided "as is" without express or implied warranty
  34.  * to the extent permitted by applicable law.
  35. ]*/
  36.  
  37. #ifdef AMIGA_AC_5
  38. # include <exec/types.h>
  39. #endif /* AMIGA_AC_5 */
  40.  
  41. #include "plot.h"
  42. #include "setshow.h"
  43.  
  44. extern int key_vpos, key_hpos, key_just;
  45. extern int datatype[];
  46. extern char timefmt[];
  47.  
  48. static void save_range __PROTO((FILE * fp, int axis, double min, double max, int autosc, char *text));
  49. static void save_tics __PROTO((FILE * fp, int where, int axis, struct ticdef * tdef, TBOOLEAN rotate, char *text));
  50. static void save_position __PROTO((FILE * fp, struct position * pos));
  51. static void save_functions__sub __PROTO((FILE * fp));
  52. static void save_variables__sub __PROTO((FILE * fp));
  53. static int lf_pop __PROTO((void));
  54. static void lf_push __PROTO((FILE * fp));
  55. static int find_maxl_cntr __PROTO((struct gnuplot_contours * contours, int *count));
  56.  
  57.  
  58. #define SAVE_NUM_OR_TIME(fp, x, axis) \
  59. do{if (datatype[axis]==TIME) { \
  60.   char s[80]; char *p; \
  61.   putc('"', fp);   \
  62.   gstrftime(s,80,timefmt,(double)(x)); \
  63.   for(p=s; *p; ++p) {\
  64.    if ( *p == '\t' ) fputs("\\t",fp);\
  65.    else if (*p == '\n') fputs("\\n",fp); \
  66.    else if ( *p > 126 || *p < 32 ) fprintf(fp,"\\%03o",*p);\
  67.    else putc(*p, fp);\
  68.   }\
  69.   putc('"', fp);\
  70.  } else {\
  71.   fprintf(fp,"%g",x);\
  72. }} while(0)
  73.  
  74.  
  75. /* State information for load_file(), to recover from errors
  76.  * and properly handle recursive load_file calls
  77.  */
  78. typedef struct lf_state_struct LFS;
  79. struct lf_state_struct {
  80.     FILE *fp;            /* file pointer for load file */
  81.     char *name;            /* name of file */
  82.     TBOOLEAN interactive;    /* value of interactive flag on entry */
  83.     TBOOLEAN do_load_arg_substitution;    /* likewise ... */
  84.     int inline_num;        /* inline_num on entry */
  85.     LFS *prev;            /* defines a stack */
  86.     char *call_args[10];    /* args when file is 'call'ed instead of 'load'ed */
  87. } *lf_head = NULL;        /* NULL if not in load_file */
  88.  
  89. /* these two could be in load_file, except for error recovery */
  90. extern TBOOLEAN do_load_arg_substitution;
  91. extern char *call_args[10];
  92.  
  93. /*
  94.  * cp_alloc() allocates a curve_points structure that can hold 'num'
  95.  * points.
  96.  */
  97. struct curve_points *
  98.  cp_alloc(num)
  99. int num;
  100. {
  101.     struct curve_points *cp;
  102.  
  103.     cp = (struct curve_points *) gp_alloc((unsigned long) sizeof(struct curve_points), "curve");
  104.     cp->p_max = (num >= 0 ? num : 0);
  105.  
  106.     if (num > 0) {
  107.     cp->points = (struct coordinate GPHUGE *)
  108.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
  109.     } else
  110.     cp->points = (struct coordinate GPHUGE *) NULL;
  111.     cp->next_cp = NULL;
  112.     cp->title = NULL;
  113.     return (cp);
  114. }
  115.  
  116.  
  117. /*
  118.  * cp_extend() reallocates a curve_points structure to hold "num"
  119.  * points. This will either expand or shrink the storage.
  120.  */
  121. void cp_extend(cp, num)
  122. struct curve_points *cp;
  123. int num;
  124. {
  125.  
  126. #if defined(DOS16) || defined(WIN16)
  127.     /* Make sure we do not allocate more than 64k points in msdos since 
  128.        * indexing is done with 16-bit int
  129.        * Leave some bytes for malloc maintainance.
  130.      */
  131.     if (num > 32700)
  132.     int_error("Array index must be less than 32k in msdos", NO_CARET);
  133. #endif /* MSDOS */
  134.  
  135.     if (num == cp->p_max)
  136.     return;
  137.  
  138.     if (num > 0) {
  139.     if (cp->points == NULL) {
  140.         cp->points = (struct coordinate GPHUGE *)
  141.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "curve points");
  142.     } else {
  143.         cp->points = (struct coordinate GPHUGE *)
  144.         gp_realloc(cp->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
  145.     }
  146.     cp->p_max = num;
  147.     } else {
  148.     if (cp->points != (struct coordinate GPHUGE *) NULL)
  149.         free(cp->points);
  150.     cp->points = (struct coordinate GPHUGE *) NULL;
  151.     cp->p_max = 0;
  152.     }
  153. }
  154.  
  155. /*
  156.  * cp_free() releases any memory which was previously malloc()'d to hold
  157.  *   curve points (and recursively down the linked list).
  158.  */
  159. void cp_free(cp)
  160. struct curve_points *cp;
  161. {
  162.     if (cp) {
  163.     cp_free(cp->next_cp);
  164.     if (cp->title)
  165.         free((char *) cp->title);
  166.     if (cp->points)
  167.         free((char *) cp->points);
  168.     free((char *) cp);
  169.     }
  170. }
  171.  
  172. /*
  173.  * iso_alloc() allocates a iso_curve structure that can hold 'num'
  174.  * points.
  175.  */
  176. struct iso_curve *
  177.  iso_alloc(num)
  178. int num;
  179. {
  180.     struct iso_curve *ip;
  181.     ip = (struct iso_curve *) gp_alloc((unsigned long) sizeof(struct iso_curve), "iso curve");
  182.     ip->p_max = (num >= 0 ? num : 0);
  183.     if (num > 0) {
  184.     ip->points = (struct coordinate GPHUGE *)
  185.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
  186.     } else
  187.     ip->points = (struct coordinate GPHUGE *) NULL;
  188.     ip->next = NULL;
  189.     return (ip);
  190. }
  191.  
  192. /*
  193.  * iso_extend() reallocates a iso_curve structure to hold "num"
  194.  * points. This will either expand or shrink the storage.
  195.  */
  196. void iso_extend(ip, num)
  197. struct iso_curve *ip;
  198. int num;
  199. {
  200.     if (num == ip->p_max)
  201.     return;
  202.  
  203. #if defined(DOS16) || defined(WIN16)
  204.     /* Make sure we do not allocate more than 64k points in msdos since 
  205.        * indexing is done with 16-bit int
  206.        * Leave some bytes for malloc maintainance.
  207.      */
  208.     if (num > 32700)
  209.     int_error("Array index must be less than 32k in msdos", NO_CARET);
  210. #endif /* 16bit (Win)Doze */
  211.  
  212.     if (num > 0) {
  213.     if (ip->points == NULL) {
  214.         ip->points = (struct coordinate GPHUGE *)
  215.         gp_alloc((unsigned long) num * sizeof(struct coordinate), "iso curve points");
  216.     } else {
  217.         ip->points = (struct coordinate GPHUGE *)
  218.         gp_realloc(ip->points, (unsigned long) num * sizeof(struct coordinate), "expanding curve points");
  219.     }
  220.     ip->p_max = num;
  221.     } else {
  222.     if (ip->points != (struct coordinate GPHUGE *) NULL)
  223.         free(ip->points);
  224.     ip->points = (struct coordinate GPHUGE *) NULL;
  225.     ip->p_max = 0;
  226.     }
  227. }
  228.  
  229. /*
  230.  * iso_free() releases any memory which was previously malloc()'d to hold
  231.  *   iso curve points.
  232.  */
  233. void iso_free(ip)
  234. struct iso_curve *ip;
  235. {
  236.     if (ip) {
  237.     if (ip->points)
  238.         free((char *) ip->points);
  239.     free((char *) ip);
  240.     }
  241. }
  242.  
  243. /*
  244.  * sp_alloc() allocates a surface_points structure that can hold 'num_iso_1'
  245.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  246.  * 'num_samp_1' samples.
  247.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  248.  */
  249. struct surface_points *
  250.  sp_alloc(num_samp_1, num_iso_1, num_samp_2, num_iso_2)
  251. int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
  252. {
  253.     struct surface_points *sp;
  254.  
  255.     sp = (struct surface_points *) gp_alloc((unsigned long) sizeof(struct surface_points), "surface");
  256.     sp->next_sp = NULL;
  257.     sp->title = NULL;
  258.     sp->contours = NULL;
  259.     sp->iso_crvs = NULL;
  260.     sp->num_iso_read = 0;
  261.  
  262.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  263.     int i;
  264.     struct iso_curve *icrv;
  265.  
  266.     for (i = 0; i < num_iso_1; i++) {
  267.         icrv = iso_alloc(num_samp_2);
  268.         icrv->next = sp->iso_crvs;
  269.         sp->iso_crvs = icrv;
  270.     }
  271.     for (i = 0; i < num_iso_2; i++) {
  272.         icrv = iso_alloc(num_samp_1);
  273.         icrv->next = sp->iso_crvs;
  274.         sp->iso_crvs = icrv;
  275.     }
  276.     } else
  277.     sp->iso_crvs = (struct iso_curve *) NULL;
  278.  
  279.     return (sp);
  280. }
  281.  
  282. /*
  283.  * sp_replace() updates a surface_points structure so it can hold 'num_iso_1'
  284.  * iso-curves with 'num_samp_2' samples and 'num_iso_2' iso-curves with
  285.  * 'num_samp_1' samples.
  286.  * If, however num_iso_2 or num_samp_1 is zero no iso curves are allocated.
  287.  */
  288. void sp_replace(sp, num_samp_1, num_iso_1, num_samp_2, num_iso_2)
  289. struct surface_points *sp;
  290. int num_samp_1, num_iso_1, num_samp_2, num_iso_2;
  291. {
  292.     int i;
  293.     struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  294.  
  295.     while (icrvs) {
  296.     icrv = icrvs;
  297.     icrvs = icrvs->next;
  298.     iso_free(icrv);
  299.     }
  300.     sp->iso_crvs = NULL;
  301.  
  302.     if (num_iso_2 > 0 && num_samp_1 > 0) {
  303.     for (i = 0; i < num_iso_1; i++) {
  304.         icrv = iso_alloc(num_samp_2);
  305.         icrv->next = sp->iso_crvs;
  306.         sp->iso_crvs = icrv;
  307.     }
  308.     for (i = 0; i < num_iso_2; i++) {
  309.         icrv = iso_alloc(num_samp_1);
  310.         icrv->next = sp->iso_crvs;
  311.         sp->iso_crvs = icrv;
  312.     }
  313.     } else
  314.     sp->iso_crvs = (struct iso_curve *) NULL;
  315. }
  316.  
  317. /*
  318.  * sp_free() releases any memory which was previously malloc()'d to hold
  319.  *   surface points.
  320.  */
  321. void sp_free(sp)
  322. struct surface_points *sp;
  323. {
  324.     if (sp) {
  325.     sp_free(sp->next_sp);
  326.     if (sp->title)
  327.         free((char *) sp->title);
  328.     if (sp->contours) {
  329.         struct gnuplot_contours *cntr, *cntrs = sp->contours;
  330.  
  331.         while (cntrs) {
  332.         cntr = cntrs;
  333.         cntrs = cntrs->next;
  334.         free(cntr->coords);
  335.         free(cntr);
  336.         }
  337.     }
  338.     if (sp->iso_crvs) {
  339.         struct iso_curve *icrv, *icrvs = sp->iso_crvs;
  340.  
  341.         while (icrvs) {
  342.         icrv = icrvs;
  343.         icrvs = icrvs->next;
  344.         iso_free(icrv);
  345.         }
  346.     }
  347.     free((char *) sp);
  348.     }
  349. }
  350.  
  351.  
  352. /*
  353.  *  functions corresponding to the arguments of the GNUPLOT `save` command
  354.  */
  355. void save_functions(fp)
  356. FILE *fp;
  357. {
  358.     if (fp) {
  359.     show_version(fp);        /* I _love_ information written */
  360.     save_functions__sub(fp);    /* at the top and the end of an */
  361.     fputs("#    EOF\n", fp);    /* human readable ASCII file.   */
  362.     (void) fclose(fp);    /*                        (JFi) */
  363.     } else
  364.     os_error("Cannot open save file", c_token);
  365. }
  366.  
  367.  
  368. void save_variables(fp)
  369. FILE *fp;
  370. {
  371.     if (fp) {
  372.     show_version(fp);
  373.     save_variables__sub(fp);
  374.     fputs("#    EOF\n", fp);
  375.     (void) fclose(fp);
  376.     } else
  377.     os_error("Cannot open save file", c_token);
  378. }
  379.  
  380.  
  381. void save_set(fp)
  382. FILE *fp;
  383. {
  384.     if (fp) {
  385.     show_version(fp);
  386.     save_set_all(fp);
  387.     fputs("#    EOF\n", fp);
  388.     (void) fclose(fp);
  389.     } else
  390.     os_error("Cannot open save file", c_token);
  391. }
  392.  
  393.  
  394. void save_all(fp)
  395. FILE *fp;
  396. {
  397.     if (fp) {
  398.     show_version(fp);
  399.     save_set_all(fp);
  400.     save_functions__sub(fp);
  401.     save_variables__sub(fp);
  402.     fprintf(fp, "%s\n", replot_line);
  403.         if (wri_to_fil_last_fit_cmd(NULL)) {
  404.            fputs("## ", fp);
  405.            wri_to_fil_last_fit_cmd(fp);
  406.            putc('\n', fp);
  407.         }
  408.     fputs("#    EOF\n", fp);
  409.     (void) fclose(fp);
  410.     } else
  411.     os_error("Cannot open save file", c_token);
  412. }
  413.  
  414. /*
  415.  *  auxiliary functions
  416.  */
  417.  
  418. static void save_functions__sub(fp)
  419. FILE *fp;
  420. {
  421.     register struct udft_entry *udf = first_udf;
  422.  
  423.     while (udf) {
  424.     if (udf->definition) {
  425.         fprintf(fp, "%s\n", udf->definition);
  426.     }
  427.     udf = udf->next_udf;
  428.     }
  429. }
  430.  
  431. static void save_variables__sub(fp)
  432. FILE *fp;
  433. {
  434.     register struct udvt_entry *udv = first_udv->next_udv;    /* always skip pi */
  435.  
  436.     while (udv) {
  437.     if (!udv->udv_undef) {
  438.         fprintf(fp, "%s = ", udv->udv_name);
  439.         disp_value(fp, &(udv->udv_value));
  440.         (void) putc('\n', fp);
  441.     }
  442.     udv = udv->next_udv;
  443.     }
  444. }
  445.  
  446. void save_set_all(fp)
  447. FILE *fp;
  448. {
  449.     struct text_label *this_label;
  450.     struct arrow_def *this_arrow;
  451.     struct linestyle_def *this_linestyle;
  452.     char str[MAX_LINE_LEN + 1];
  453.  
  454.     /* opinions are split as to whether we save term and outfile
  455.      * as a compromise, we output them as comments !
  456.      */
  457.     if (term)
  458.     fprintf(fp, "# set terminal %s %s\n", term->name, term_options);
  459.     else
  460.     fputs("# set terminal unknown\n", fp);
  461.  
  462.     if (outstr)
  463.     fprintf(fp, "# set output '%s'\n", outstr);
  464.     else
  465.     fputs("# set output\n", fp);
  466.  
  467.     fprintf(fp, "\
  468. set %sclip points\n\
  469. set %sclip one\n\
  470. set %sclip two\n\
  471. set bar %f\n",
  472.         (clip_points) ? "" : "no",
  473.         (clip_lines1) ? "" : "no",
  474.         (clip_lines2) ? "" : "no",
  475.         bar_size);
  476.  
  477.     if (draw_border)
  478.     /* HBB 980609: handle border linestyle, too */
  479.     fprintf(fp, "set border %d lt %d lw %.3f\n", draw_border, border_lp.l_type + 1, border_lp.l_width);
  480.     else
  481.     fprintf(fp, "set noborder\n");
  482.  
  483.     fprintf(fp, "\
  484. set xdata%s\n\
  485. set ydata%s\n\
  486. set zdata%s\n\
  487. set x2data%s\n\
  488. set y2data%s\n",
  489.         datatype[FIRST_X_AXIS] == TIME ? " time" : "",
  490.         datatype[FIRST_Y_AXIS] == TIME ? " time" : "",
  491.         datatype[FIRST_Z_AXIS] == TIME ? " time" : "",
  492.         datatype[SECOND_X_AXIS] == TIME ? " time" : "",
  493.         datatype[SECOND_Y_AXIS] == TIME ? " time" : "");
  494.  
  495.     if (boxwidth < 0.0)
  496.     fputs("set boxwidth\n", fp);
  497.     else
  498.     fprintf(fp, "set boxwidth %g\n", boxwidth);
  499.     if (dgrid3d)
  500.     fprintf(fp, "set dgrid3d %d,%d, %d\n",
  501.         dgrid3d_row_fineness,
  502.         dgrid3d_col_fineness,
  503.         dgrid3d_norm_value);
  504.  
  505.     fprintf(fp, "\
  506. set dummy %s,%s\n\
  507. set format x \"%s\"\n\
  508. set format y \"%s\"\n\
  509. set format x2 \"%s\"\n\
  510. set format y2 \"%s\"\n\
  511. set format z \"%s\"\n\
  512. set angles %s\n",
  513.         dummy_var[0], dummy_var[1],
  514.         conv_text(str, xformat),
  515.         conv_text(str, yformat),
  516.         conv_text(str, x2format),
  517.         conv_text(str, y2format),
  518.         conv_text(str, zformat),
  519.         (angles_format == ANGLES_RADIANS) ? "radians" : "degrees");
  520.  
  521.     if (work_grid.l_type == 0)
  522.     fputs("set nogrid\n", fp);
  523.     else {
  524.     if (polar_grid_angle)    /* set angle already output */
  525.         fprintf(fp, "set grid polar %f\n", polar_grid_angle / ang2rad);
  526.     else
  527.         fputs("set grid nopolar\n", fp);
  528.     fprintf(fp, "set grid %sxtics %sytics %sztics %sx2tics %sy2tics %smxtics %smytics %smztics %smx2tics %smy2tics lt %d lw %.3f, lt %d lw %.3f\n",
  529.         work_grid.l_type & GRID_X ? "" : "no",
  530.         work_grid.l_type & GRID_Y ? "" : "no",
  531.         work_grid.l_type & GRID_Z ? "" : "no",
  532.         work_grid.l_type & GRID_X2 ? "" : "no",
  533.         work_grid.l_type & GRID_Y2 ? "" : "no",
  534.         work_grid.l_type & GRID_MX ? "" : "no",
  535.         work_grid.l_type & GRID_MY ? "" : "no",
  536.         work_grid.l_type & GRID_MZ ? "" : "no",
  537.         work_grid.l_type & GRID_MX2 ? "" : "no",
  538.         work_grid.l_type & GRID_MY2 ? "" : "no",
  539.         grid_lp.l_type + 1, grid_lp.l_width,
  540.         mgrid_lp.l_type + 1, mgrid_lp.l_width);
  541.     }
  542.     fprintf(fp, "set key title \"%s\"\n", conv_text(str, key_title));
  543.     switch (key) {
  544.     case -1:{
  545.         fputs("set key", fp);
  546.         switch (key_hpos) {
  547.         case TRIGHT:
  548.         fputs(" right", fp);
  549.         break;
  550.         case TLEFT:
  551.         fputs(" left", fp);
  552.         break;
  553.         case TOUT:
  554.         fputs(" out", fp);
  555.         break;
  556.         }
  557.         switch (key_vpos) {
  558.         case TTOP:
  559.         fputs(" top", fp);
  560.         break;
  561.         case TBOTTOM:
  562.         fputs(" bottom", fp);
  563.         break;
  564.         case TUNDER:
  565.         fputs(" below", fp);
  566.         break;
  567.         }
  568.         break;
  569.     }
  570.     case 0:
  571.     fputs("set nokey\n", fp);
  572.     break;
  573.     case 1:
  574.     fputs("set key ", fp);
  575.     save_position(fp, &key_user_pos);
  576.     break;
  577.     }
  578.     if (key) {
  579.     fprintf(fp, " %s %sreverse box linetype %d linewidth %.3f samplen %g spacing %g width %g\n",
  580.         key_just == JLEFT ? "Left" : "Right",
  581.         key_reverse ? "" : "no",
  582.         key_box.l_type + 1, key_box.l_width, key_swidth, key_vert_factor, key_width_fix);
  583.     }
  584.     fputs("set nolabel\n", fp);
  585.     for (this_label = first_label; this_label != NULL;
  586.      this_label = this_label->next) {
  587.     fprintf(fp, "set label %d \"%s\" at ",
  588.         this_label->tag,
  589.         conv_text(str, this_label->text));
  590.     save_position(fp, &this_label->place);
  591.  
  592.     switch (this_label->pos) {
  593.     case LEFT:
  594.         fputs(" left", fp);
  595.         break;
  596.     case CENTRE:
  597.         fputs(" centre", fp);
  598.         break;
  599.     case RIGHT:
  600.         fputs(" right", fp);
  601.         break;
  602.     }
  603.     fprintf(fp, " %srotate", this_label->rotate ? "" : "no");
  604.     if ((this_label->font)[0] != NUL)
  605.         fprintf(fp, " font \"%s\"", this_label->font);
  606.     /* Entry font added by DJL */
  607.     fputc('\n', fp);
  608.     }
  609.     fputs("set noarrow\n", fp);
  610.     for (this_arrow = first_arrow; this_arrow != NULL;
  611.      this_arrow = this_arrow->next) {
  612.     fprintf(fp, "set arrow %d from ", this_arrow->tag);
  613.     save_position(fp, &this_arrow->start);
  614.     fputs(" to ", fp);
  615.     save_position(fp, &this_arrow->end);
  616.     fprintf(fp, " %s linetype %d linewidth %.3f\n",
  617.         this_arrow->head ? "" : " nohead",
  618.         this_arrow->lp_properties.l_type + 1,
  619.         this_arrow->lp_properties.l_width);
  620.     }
  621.     fputs("set nolinestyle\n", fp);
  622.     for (this_linestyle = first_linestyle; this_linestyle != NULL;
  623.      this_linestyle = this_linestyle->next) {
  624.     fprintf(fp, "set linestyle %d ", this_linestyle->tag);
  625.     fprintf(fp, "linetype %d linewidth %.3f pointtype %d pointsize %.3f\n",
  626.         this_linestyle->lp_properties.l_type + 1,
  627.         this_linestyle->lp_properties.l_width,
  628.         this_linestyle->lp_properties.p_type + 1,
  629.         this_linestyle->lp_properties.p_size);
  630.     }
  631.     fputs("set nologscale\n", fp);
  632.     if (is_log_x)
  633.     fprintf(fp, "set logscale x %g\n", base_log_x);
  634.     if (is_log_y)
  635.     fprintf(fp, "set logscale y %g\n", base_log_y);
  636.     if (is_log_z)
  637.     fprintf(fp, "set logscale z %g\n", base_log_z);
  638.     if (is_log_x2)
  639.     fprintf(fp, "set logscale x2 %g\n", base_log_x2);
  640.     if (is_log_y2)
  641.     fprintf(fp, "set logscale y2 %g\n", base_log_y2);
  642.  
  643.     fprintf(fp, "\
  644. set offsets %g, %g, %g, %g\n\
  645. set pointsize %g\n\
  646. set encoding %s\n\
  647. set %spolar\n\
  648. set %sparametric\n\
  649. set view %g, %g, %g, %g\n\
  650. set samples %d, %d\n\
  651. set isosamples %d, %d\n\
  652. set %ssurface\n\
  653. set %scontour",
  654.         loff, roff, toff, boff,
  655.         pointsize,
  656.         encoding_names[encoding],
  657.         (polar) ? "" : "no",
  658.         (parametric) ? "" : "no",
  659.         surface_rot_x, surface_rot_z, surface_scale, surface_zscale,
  660.         samples_1, samples_2,
  661.         iso_samples_1, iso_samples_2,
  662.         (draw_surface) ? "" : "no",
  663.         (draw_contour) ? "" : "no");
  664.  
  665.     switch (draw_contour) {
  666.     case CONTOUR_NONE:
  667.     fputc('\n', fp);
  668.     break;
  669.     case CONTOUR_BASE:
  670.     fputs(" base\n", fp);
  671.     break;
  672.     case CONTOUR_SRF:
  673.     fputs(" surface\n", fp);
  674.     break;
  675.     case CONTOUR_BOTH:
  676.     fputs(" both\n", fp);
  677.     break;
  678.     }
  679.     if (label_contours)
  680.     fprintf(fp, "set clabel '%s'\n", contour_format);
  681.     else
  682.     fputs("set noclabel\n", fp);
  683.  
  684.     fputs("set mapping ", fp);
  685.     switch(mapping3d) {
  686.     case MAP3D_SPHERICAL:
  687.     fputs("spherical\n", fp);
  688.     break;
  689.     case MAP3D_CYLINDRICAL:
  690.     fputs("cylindrical\n", fp);
  691.     break;
  692.     case MAP3D_CARTESIAN:
  693.     default:
  694.     fputs("cartesian\n", fp);
  695.     break;
  696.     }
  697.  
  698.     if (missing_val != NULL)
  699.     fprintf(fp, "set missing %s\n", missing_val);
  700.  
  701.     save_hidden3doptions(fp);
  702.     fprintf(fp, "set cntrparam order %d\n", contour_order);
  703.     fputs("set cntrparam ", fp);
  704.     switch (contour_kind) {
  705.     case CONTOUR_KIND_LINEAR:
  706.     fputs("linear\n", fp);
  707.     break;
  708.     case CONTOUR_KIND_CUBIC_SPL:
  709.     fputs("cubicspline\n", fp);
  710.     break;
  711.     case CONTOUR_KIND_BSPLINE:
  712.     fputs("bspline\n", fp);
  713.     break;
  714.     }
  715.     fputs("set cntrparam levels ", fp);
  716.     switch (levels_kind) {
  717.     case LEVELS_AUTO:
  718.     fprintf(fp, "auto %d\n", contour_levels);
  719.     break;
  720.     case LEVELS_INCREMENTAL:
  721.     fprintf(fp, "incremental %g,%g,%g\n",
  722.         levels_list[0], levels_list[1],
  723.         levels_list[0] + levels_list[1] * contour_levels);
  724.     break;
  725.     case LEVELS_DISCRETE:
  726.     {
  727.         int i;
  728.         fprintf(fp, "discrete %g", levels_list[0]);
  729.         for (i = 1; i < contour_levels; i++)
  730.         fprintf(fp, ",%g ", levels_list[i]);
  731.         fputc('\n', fp);
  732.     }
  733.     }
  734.     fprintf(fp, "\
  735. set cntrparam points %d\n\
  736. set size ratio %g %g,%g\n\
  737. set origin %g,%g\n\
  738. set data style ",
  739.         contour_pts,
  740.         aspect_ratio, xsize, ysize,
  741.         xoffset, yoffset);
  742.  
  743.     switch (data_style) {
  744.     case LINES:
  745.     fputs("lines\n", fp);
  746.     break;
  747.     case POINTSTYLE:
  748.     fputs("points\n", fp);
  749.     break;
  750.     case IMPULSES:
  751.     fputs("impulses\n", fp);
  752.     break;
  753.     case LINESPOINTS:
  754.     fputs("linespoints\n", fp);
  755.     break;
  756.     case DOTS:
  757.     fputs("dots\n", fp);
  758.     break;
  759.     case YERRORBARS:
  760.     fputs("yerrorbars\n", fp);
  761.     break;
  762.     case XERRORBARS:
  763.     fputs("xerrorbars\n", fp);
  764.     break;
  765.     case XYERRORBARS:
  766.     fputs("xyerrorbars\n", fp);
  767.     break;
  768.     case BOXES:
  769.     fputs("boxes\n", fp);
  770.     break;
  771.     case BOXERROR:
  772.     fputs("boxerrorbars\n", fp);
  773.     break;
  774.     case BOXXYERROR:
  775.     fputs("boxxyerrorbars\n", fp);
  776.     break;
  777.     case STEPS:
  778.     fputs("steps\n", fp);
  779.     break;            /* JG */
  780.     case FSTEPS:
  781.     fputs("fsteps\n", fp);
  782.     break;            /* HOE */
  783.     case HISTEPS:
  784.     fputs("histeps\n", fp);
  785.     break;            /* CAC */
  786.     case VECTOR:
  787.     fputs("vector\n", fp);
  788.     break;
  789.     case FINANCEBARS:
  790.     fputs("financebars\n", fp);
  791.     break;
  792.     case CANDLESTICKS:
  793.     fputs("candlesticks\n", fp);
  794.     break;
  795.     }
  796.     fputs("set function style ", fp);
  797.     switch (func_style) {
  798.     case LINES:
  799.     fputs("lines\n", fp);
  800.     break;
  801.     case POINTSTYLE:
  802.     fputs("points\n", fp);
  803.     break;
  804.     case IMPULSES:
  805.     fputs("impulses\n", fp);
  806.     break;
  807.     case LINESPOINTS:
  808.     fputs("linespoints\n", fp);
  809.     break;
  810.     case DOTS:
  811.     fputs("dots\n", fp);
  812.     break;
  813.     case YERRORBARS:
  814.     fputs("yerrorbars\n", fp);
  815.     break;
  816.     case XERRORBARS:
  817.     fputs("xerrorbars\n", fp);
  818.     break;
  819.     case XYERRORBARS:
  820.     fputs("xyerrorbars\n", fp);
  821.     break;
  822.     case BOXXYERROR:
  823.     fputs("boxxyerrorbars\n", fp);
  824.     break;
  825.     case BOXES:
  826.     fputs("boxes\n", fp);
  827.     break;
  828.     case BOXERROR:
  829.     fputs("boxerrorbars\n", fp);
  830.     break;
  831.     case STEPS:
  832.     fputs("steps\n", fp);
  833.     break;            /* JG */
  834.     case FSTEPS:
  835.     fputs("fsteps\n", fp);
  836.     break;            /* HOE */
  837.     case HISTEPS:
  838.     fputs("histeps\n", fp);
  839.     break;            /* CAC */
  840.     case VECTOR:
  841.     fputs("vector\n", fp);
  842.     break;
  843.     case FINANCEBARS:
  844.     fputs("financebars\n", fp);
  845.     break;
  846.     case CANDLESTICKS:
  847.     fputs("candlesticks\n", fp);
  848.     break;
  849.     default:
  850.         /* HBB: default case demanded by gcc, still needed ?? */
  851.     fputs("---error!---\n", fp);
  852.     }
  853.  
  854.     fprintf(fp, "\
  855. set xzeroaxis lt %d lw %.3f\n\
  856. set x2zeroaxis lt %d lw %.3f\n\
  857. set yzeroaxis lt %d lw %.3f\n\
  858. set y2zeroaxis lt %d lw %.3f\n\
  859. set tics %s\n\
  860. set ticslevel %g\n\
  861. set ticscale %g %g\n",
  862.         xzeroaxis.l_type + 1, xzeroaxis.l_width,
  863.         x2zeroaxis.l_type + 1, x2zeroaxis.l_width,
  864.         yzeroaxis.l_type + 1, yzeroaxis.l_width,
  865.         y2zeroaxis.l_type + 1, y2zeroaxis.l_width,
  866.         (tic_in) ? "in" : "out",
  867.         ticslevel,
  868.         ticscale, miniticscale);
  869.  
  870. #define SAVE_XYZLABEL(name,lab) { \
  871.   fprintf(fp, "set %s \"%s\" %f,%f ", \
  872.     name, conv_text(str,lab.text),lab.xoffset,lab.yoffset); \
  873.   fprintf(fp, " \"%s\"\n", conv_text(str, lab.font)); \
  874. }
  875.  
  876.  
  877. #define SAVE_MINI(name,m,freq) switch(m&TICS_MASK) { \
  878.  case 0: fprintf(fp, "set no%s\n", name); break; \
  879.  case MINI_AUTO: fprintf(fp, "set %s\n",name); break; \
  880.  case MINI_DEFAULT: fprintf(fp, "set %s default\n",name); break; \
  881.  case MINI_USER: fprintf(fp, "set %s %f\n", name, freq); break; \
  882. }
  883.     SAVE_MINI("mxtics", mxtics, mxtfreq)
  884.     SAVE_MINI("mytics", mytics, mytfreq)
  885.     SAVE_MINI("mx2tics", mx2tics, mx2tfreq)
  886.     SAVE_MINI("my2tics", my2tics, my2tfreq)
  887.     save_tics(fp, xtics, FIRST_X_AXIS, &xticdef, rotate_xtics, "x");
  888.     save_tics(fp, ytics, FIRST_Y_AXIS, &yticdef, rotate_ytics, "y");
  889.     save_tics(fp, ztics, FIRST_Z_AXIS, &zticdef, rotate_ztics, "z");
  890.     save_tics(fp, x2tics, SECOND_X_AXIS, &x2ticdef, rotate_x2tics, "x2");
  891.     save_tics(fp, y2tics, SECOND_Y_AXIS, &y2ticdef, rotate_y2tics, "y2");
  892.     SAVE_XYZLABEL("title", title);
  893.  
  894.     fprintf(fp, "set %s \"%s\" %s %srotate %f,%f ",
  895.         "timestamp", conv_text(str, timelabel.text),
  896.         (timelabel_bottom ? "bottom" : "top"),
  897.         (timelabel_rotate ? "" : "no"),
  898.         timelabel.xoffset, timelabel.yoffset);
  899.     fprintf(fp, " \"%s\"\n", conv_text(str, timelabel.font));
  900.  
  901.     save_range(fp, R_AXIS, rmin, rmax, autoscale_r, "r");
  902.     save_range(fp, T_AXIS, tmin, tmax, autoscale_t, "t");
  903.     save_range(fp, U_AXIS, umin, umax, autoscale_u, "u");
  904.     save_range(fp, V_AXIS, vmin, vmax, autoscale_v, "v");
  905.  
  906.     SAVE_XYZLABEL("xlabel", xlabel);
  907.     SAVE_XYZLABEL("x2label", x2label);
  908.  
  909.     if (strlen(timefmt)) {
  910.     fprintf(fp, "set timefmt \"%s\"\n", conv_text(str, timefmt));
  911.     }
  912.     save_range(fp, FIRST_X_AXIS, xmin, xmax, autoscale_x, "x");
  913.     save_range(fp, SECOND_X_AXIS, x2min, x2max, autoscale_x2, "x2");
  914.  
  915.     SAVE_XYZLABEL("ylabel", ylabel);
  916.     SAVE_XYZLABEL("y2label", y2label);
  917.  
  918.     save_range(fp, FIRST_Y_AXIS, ymin, ymax, autoscale_y, "y");
  919.     save_range(fp, SECOND_Y_AXIS, y2min, y2max, autoscale_y2, "y2");
  920.  
  921.     SAVE_XYZLABEL("zlabel", zlabel);
  922.     save_range(fp, FIRST_Z_AXIS, zmin, zmax, autoscale_z, "z");
  923.  
  924.     fprintf(fp, "set zero %g\n", zero);
  925.     fprintf(fp, "set lmargin %d\nset bmargin %d\nset rmargin %d\nset tmargin %d\n",
  926.         lmargin, bmargin, rmargin, tmargin);
  927.  
  928.     fprintf(fp, "set locale \"%s\"\n", cur_locale);
  929. }
  930.  
  931. static void save_tics(fp, where, axis, tdef, rotate, text)
  932. FILE *fp;
  933. int where;
  934. int axis;
  935. struct ticdef *tdef;
  936. TBOOLEAN rotate;
  937. char *text;
  938. {
  939.     char str[MAX_LINE_LEN + 1];
  940.  
  941.     if (where == NO_TICS) {
  942.     fprintf(fp, "set no%stics\n", text);
  943.     return;
  944.     }
  945.     fprintf(fp, "set %stics %s %smirror %srotate ", text,
  946.         (where & TICS_MASK) == TICS_ON_AXIS ? "axis" : "border",
  947.         (where & TICS_MIRROR) ? "" : "no", rotate ? "" : "no");
  948.     switch (tdef->type) {
  949.     case TIC_COMPUTED:{
  950.         fputs("autofreq ", fp);
  951.         break;
  952.     }
  953.     case TIC_MONTH:{
  954.         fprintf(fp, "\nset %smtics", text);
  955.         break;
  956.     }
  957.     case TIC_DAY:{
  958.         fprintf(fp, "\nset %cdtics", axis);
  959.         break;
  960.     }
  961.     case TIC_SERIES:
  962.     if (datatype[axis] == TIME) {
  963.         if (tdef->def.series.start != -VERYLARGE) {
  964.         char fd[26];
  965.         gstrftime(fd, 24, timefmt, (double) tdef->def.series.start);
  966.         fprintf(fp, "\"%s\",", conv_text(str, fd));
  967.         }
  968.         fprintf(fp, "%g", tdef->def.series.incr);
  969.  
  970.         if (tdef->def.series.end != VERYLARGE) {
  971.         char td[26];
  972.         gstrftime(td, 24, timefmt, (double) tdef->def.series.end);
  973.         fprintf(fp, ",\"%s\"", conv_text(str, td));
  974.         }
  975.     } else {        /* !TIME */
  976.  
  977.         if (tdef->def.series.start != -VERYLARGE)
  978.         fprintf(fp, "%g,", tdef->def.series.start);
  979.         fprintf(fp, "%g", tdef->def.series.incr);
  980.         if (tdef->def.series.end != VERYLARGE)
  981.         fprintf(fp, ",%g", tdef->def.series.end);
  982.     }
  983.  
  984.     break;
  985.  
  986.     case TIC_USER:{
  987.         register struct ticmark *t;
  988.         int flag_time;
  989.         flag_time = (datatype[axis] == TIME);
  990.         fputs(" (", fp);
  991.         for (t = tdef->def.user; t != NULL; t = t->next) {
  992.         if (t->label)
  993.             fprintf(fp, "\"%s\" ", conv_text(str, t->label));
  994.         if (flag_time) {
  995.             char td[26];
  996.             gstrftime(td, 24, timefmt, (double) t->position);
  997.             fprintf(fp, "\"%s\"", conv_text(str, td));
  998.         } else {
  999.             fprintf(fp, "%g", t->position);
  1000.         }
  1001.         if (t->next) {
  1002.             fputs(", ", fp);
  1003.         }
  1004.         }
  1005.         fputs(")", fp);
  1006.         break;
  1007.     }
  1008.     }
  1009.     putc('\n', fp);
  1010. }
  1011.  
  1012. static void save_position(fp, pos)
  1013. FILE *fp;
  1014. struct position *pos;
  1015. {
  1016.     static char *msg[] =
  1017.     {"first_axes ", "second axes ", "graph ", "screen "};
  1018.  
  1019.     assert(first_axes == 0 && second_axes == 1 && graph == 2 && screen == 3);
  1020.  
  1021.     fprintf(fp, "%s%g, %s%g, %s%g",
  1022.         pos->scalex == first_axes ? "" : msg[pos->scalex], pos->x,
  1023.         pos->scaley == pos->scalex ? "" : msg[pos->scaley], pos->y,
  1024.         pos->scalez == pos->scaley ? "" : msg[pos->scalez], pos->z);
  1025. }
  1026.  
  1027. void load_file(fp, name, can_do_args)
  1028. FILE *fp;
  1029. char *name;
  1030. TBOOLEAN can_do_args;
  1031. {
  1032.     register int len;
  1033.  
  1034.     int start, left;
  1035.     int more;
  1036.     int stop = FALSE;
  1037.  
  1038.     lf_push(fp);        /* save state for errors and recursion */
  1039.     do_load_arg_substitution = can_do_args;
  1040.  
  1041.     if (fp == (FILE *) NULL) {
  1042.     /* HBB 980311: alloc() it, to save valuable stack space: */
  1043.     char *errbuf = gp_alloc(BUFSIZ, "load_file errorstring");
  1044.     (void) sprintf(errbuf, "Cannot open %s file '%s'",
  1045.                can_do_args ? "call" : "load", name);
  1046.     os_error(errbuf, c_token);
  1047.     free(errbuf);
  1048.     } else if (fp == stdin) {
  1049.     /* DBT 10-6-98  go interactive if "-" named as load file */
  1050.     interactive = TRUE; 
  1051.     while(!com_line())
  1052.         ;
  1053.     } else {
  1054.     /* go into non-interactive mode during load */
  1055.     /* will be undone below, or in load_file_error */
  1056.     interactive = FALSE;
  1057.     inline_num = 0;
  1058.     infile_name = name;
  1059.  
  1060.     if (can_do_args) {
  1061.         int aix = 0;
  1062.         while (++c_token < num_tokens && aix <= 9) {
  1063.         if (isstring(c_token))
  1064.             m_quote_capture(&call_args[aix++], c_token, c_token);
  1065.         else
  1066.             m_capture(&call_args[aix++], c_token, c_token);
  1067.         }
  1068.  
  1069. /*         A GNUPLOT "call" command can have up to _10_ arguments named "$0"
  1070.    to "$9".  After reading the 10th argument (i.e.: "$9") the variable
  1071.    'aix' contains the value '10' because of the 'aix++' construction
  1072.    in '&call_args[aix++]'.  So I think the following test of 'aix' 
  1073.    should be done against '10' instead of '9'.                (JFi) */
  1074.  
  1075. /*              if (c_token >= num_tokens && aix > 9) */
  1076.         if (c_token >= num_tokens && aix > 10)
  1077.         int_error("too many arguments for CALL <file>", ++c_token);
  1078.     }
  1079.     while (!stop) {        /* read all commands in file */
  1080.         /* read one command */
  1081.         left = input_line_len;
  1082.         start = 0;
  1083.         more = TRUE;
  1084.  
  1085.         while (more) {
  1086.         if (fgets(&(input_line[start]), left, fp) == (char *) NULL) {
  1087.             stop = TRUE;    /* EOF in file */
  1088.             input_line[start] = '\0';
  1089.             more = FALSE;
  1090.         } else {
  1091.             inline_num++;
  1092.             len = strlen(input_line) - 1;
  1093.             if (input_line[len] == '\n') {    /* remove any newline */
  1094.             input_line[len] = '\0';
  1095.             /* Look, len was 1-1 = 0 before, take care here! */
  1096.             if (len > 0)
  1097.                 --len;
  1098.             if (input_line[len] == '\r') {    /* remove any carriage return */
  1099.                 input_line[len] = NUL;
  1100.                 if (len > 0)
  1101.                 --len;
  1102.             }
  1103.             }
  1104.              else if (len + 2 >= left) {
  1105.             extend_input_line();
  1106.             left = input_line_len - len - 1;
  1107.             start = len + 1;
  1108.             continue;    /* don't check for '\' */
  1109.             }
  1110.             if (input_line[len] == '\\') {
  1111.             /* line continuation */
  1112.             start = len;
  1113.             left = input_line_len - start;
  1114.             } else
  1115.             more = FALSE;
  1116.         }
  1117.         }
  1118.  
  1119.         if (strlen(input_line) > 0) {
  1120.         if (can_do_args) {
  1121.             register int il = 0;
  1122.             register char *rl;
  1123.             char *raw_line = rl = gp_alloc((unsigned long) strlen(input_line) + 1, "string");
  1124.  
  1125.             strcpy(raw_line, input_line);
  1126.             *input_line = '\0';
  1127.             while (*rl) {
  1128.             register int aix;
  1129.             if (*rl == '$'
  1130.                 && ((aix = *(++rl)) != 0)    /* HBB 980308: quiet BCC warning */
  1131.                 &&aix >= '0' && aix <= '9') {
  1132.                 if (call_args[aix -= '0']) {
  1133.                 len = strlen(call_args[aix]);
  1134.                 while (input_line_len - il < len + 1) {
  1135.                     extend_input_line();
  1136.                 }
  1137.                 strcpy(input_line + il, call_args[aix]);
  1138.                 il += len;
  1139.                 }
  1140.             } else {
  1141.                 /* substitute for $<n> here */
  1142.                 if (il + 1 > input_line_len) {
  1143.                 extend_input_line();
  1144.                 }
  1145.                 input_line[il++] = *rl;
  1146.             }
  1147.             rl++;
  1148.             }
  1149.             if (il + 1 > input_line_len) {
  1150.             extend_input_line();
  1151.             }
  1152.             input_line[il] = '\0';
  1153.             free(raw_line);
  1154.         }
  1155.         screen_ok = FALSE;    /* make sure command line is
  1156.                        echoed on error */
  1157.         do_line();
  1158.         }
  1159.     }
  1160.     }
  1161.  
  1162.     /* pop state */
  1163.     (void) lf_pop();        /* also closes file fp */
  1164. }
  1165.  
  1166. /* pop from load_file state stack */
  1167. static TBOOLEAN            /* FALSE if stack was empty */
  1168.  lf_pop()
  1169. {                /* called by load_file and load_file_error */
  1170.     LFS *lf;
  1171.  
  1172.     if (lf_head == NULL)
  1173.     return (FALSE);
  1174.     else {
  1175.     int argindex;
  1176.     lf = lf_head;
  1177.     if (lf->fp != (FILE *)NULL && lf->fp != stdin) {
  1178.         /* DBT 10-6-98  do not close stdin in the case
  1179.          * that "-" is named as a load file
  1180.          */
  1181.         (void) fclose(lf->fp);
  1182.     }
  1183.     for (argindex = 0; argindex < 10; argindex++) {
  1184.         if (call_args[argindex]) {
  1185.         free(call_args[argindex]);
  1186.         }
  1187.         call_args[argindex] = lf->call_args[argindex];
  1188.     }
  1189.     do_load_arg_substitution = lf->do_load_arg_substitution;
  1190.     interactive = lf->interactive;
  1191.     inline_num = lf->inline_num;
  1192.     infile_name = lf->name;
  1193.     lf_head = lf->prev;
  1194.     free((char *) lf);
  1195.     return (TRUE);
  1196.     }
  1197. }
  1198.  
  1199. /* push onto load_file state stack */
  1200. /* essentially, we save information needed to undo the load_file changes */
  1201. static void lf_push(fp)        /* called by load_file */
  1202. FILE *fp;
  1203. {
  1204.     LFS *lf;
  1205.     int argindex;
  1206.  
  1207.     lf = (LFS *) gp_alloc((unsigned long) sizeof(LFS), (char *) NULL);
  1208.     if (lf == (LFS *) NULL) {
  1209.     if (fp != (FILE *) NULL)
  1210.         (void) fclose(fp);    /* it won't be otherwise */
  1211.     int_error("not enough memory to load file", c_token);
  1212.     }
  1213.     lf->fp = fp;        /* save this file pointer */
  1214.     lf->name = infile_name;    /* save current name */
  1215.     lf->interactive = interactive;    /* save current state */
  1216.     lf->inline_num = inline_num;    /* save current line number */
  1217.     lf->do_load_arg_substitution = do_load_arg_substitution;
  1218.     for (argindex = 0; argindex < 10; argindex++) {
  1219.     lf->call_args[argindex] = call_args[argindex];
  1220.     call_args[argindex] = NULL;    /* initially no args */
  1221.     }
  1222.     lf->prev = lf_head;        /* link to stack */
  1223.     lf_head = lf;
  1224. }
  1225.  
  1226. /* used for reread  vsnyder@math.jpl.nasa.gov */
  1227. FILE *lf_top()
  1228. {
  1229.     if (lf_head == (LFS *) NULL)
  1230.     return ((FILE *) NULL);
  1231.     return (lf_head->fp);
  1232. }
  1233.  
  1234. /* called from main */
  1235. void load_file_error()
  1236. {
  1237.     /* clean up from error in load_file */
  1238.     /* pop off everything on stack */
  1239.     while (lf_pop());
  1240. }
  1241.  
  1242. /* find char c in string str; return p such that str[p]==c;
  1243.  * if c not in str then p=strlen(str)
  1244.  */
  1245. int instring(str, c)
  1246. char *str;
  1247. int c;
  1248. {
  1249.     int pos = 0;
  1250.  
  1251.     while (str != NULL && *str != NUL && c != *str) {
  1252.     str++;
  1253.     pos++;
  1254.     }
  1255.     return (pos);
  1256. }
  1257.  
  1258. void show_functions()
  1259. {
  1260.     register struct udft_entry *udf = first_udf;
  1261.  
  1262.     fputs("\n\tUser-Defined Functions:\n", stderr);
  1263.  
  1264.     while (udf) {
  1265.     if (udf->definition)
  1266.         fprintf(stderr, "\t%s\n", udf->definition);
  1267.     else
  1268.         fprintf(stderr, "\t%s is undefined\n", udf->udf_name);
  1269.     udf = udf->next_udf;
  1270.     }
  1271. }
  1272.  
  1273.  
  1274. void show_at()
  1275. {
  1276.     (void) putc('\n', stderr);
  1277.     disp_at(temp_at(), 0);
  1278. }
  1279.  
  1280.  
  1281. void disp_at(curr_at, level)
  1282. struct at_type *curr_at;
  1283. int level;
  1284. {
  1285.     register int i, j;
  1286.     register union argument *arg;
  1287.  
  1288.     for (i = 0; i < curr_at->a_count; i++) {
  1289.     (void) putc('\t', stderr);
  1290.     for (j = 0; j < level; j++)
  1291.         (void) putc(' ', stderr);    /* indent */
  1292.  
  1293.     /* print name of instruction */
  1294.  
  1295.     fputs(ft[(int) (curr_at->actions[i].index)].f_name, stderr);
  1296.     arg = &(curr_at->actions[i].arg);
  1297.  
  1298.     /* now print optional argument */
  1299.  
  1300.     switch (curr_at->actions[i].index) {
  1301.     case PUSH:
  1302.         fprintf(stderr, " %s\n", arg->udv_arg->udv_name);
  1303.         break;
  1304.     case PUSHC:
  1305.         (void) putc(' ', stderr);
  1306.         disp_value(stderr, &(arg->v_arg));
  1307.         (void) putc('\n', stderr);
  1308.         break;
  1309.     case PUSHD1:
  1310.         fprintf(stderr, " %c dummy\n",
  1311.             arg->udf_arg->udf_name[0]);
  1312.         break;
  1313.     case PUSHD2:
  1314.         fprintf(stderr, " %c dummy\n",
  1315.             arg->udf_arg->udf_name[1]);
  1316.         break;
  1317.     case CALL:
  1318.         fprintf(stderr, " %s", arg->udf_arg->udf_name);
  1319.         if (level < 6) {
  1320.         if (arg->udf_arg->at) {
  1321.             (void) putc('\n', stderr);
  1322.             disp_at(arg->udf_arg->at, level + 2);    /* recurse! */
  1323.         } else
  1324.             fputs(" (undefined)\n", stderr);
  1325.         } else
  1326.         (void) putc('\n', stderr);
  1327.         break;
  1328.     case CALLN:
  1329.         fprintf(stderr, " %s", arg->udf_arg->udf_name);
  1330.         if (level < 6) {
  1331.         if (arg->udf_arg->at) {
  1332.             (void) putc('\n', stderr);
  1333.             disp_at(arg->udf_arg->at, level + 2);    /* recurse! */
  1334.         } else
  1335.             fputs(" (undefined)\n", stderr);
  1336.         } else
  1337.         (void) putc('\n', stderr);
  1338.         break;
  1339.     case JUMP:
  1340.     case JUMPZ:
  1341.     case JUMPNZ:
  1342.     case JTERN:
  1343.         fprintf(stderr, " +%d\n", arg->j_arg);
  1344.         break;
  1345.     case DOLLARS:
  1346.         fprintf(stderr, " %d\n", arg->v_arg.v.int_val);
  1347.         break;
  1348.     default:
  1349.         (void) putc('\n', stderr);
  1350.     }
  1351.     }
  1352. }
  1353.  
  1354. /* find max len of keys and count keys with len > 0 */
  1355.  
  1356. int find_maxl_keys(plots, count, kcnt)
  1357. struct curve_points *plots;
  1358. int count, *kcnt;
  1359. {
  1360.     int mlen, len, curve, cnt;
  1361.     register struct curve_points *this_plot;
  1362.  
  1363.     mlen = cnt = 0;
  1364.     this_plot = plots;
  1365.     for (curve = 0; curve < count; this_plot = this_plot->next_cp, curve++)
  1366.     if (this_plot->title
  1367.         && ((len = /*assign */ strlen(this_plot->title)) != 0)    /* HBB 980308: quiet BCC warning */
  1368.         ) {
  1369.         cnt++;
  1370.         if (len > mlen)
  1371.         mlen = strlen(this_plot->title);
  1372.     }
  1373.     if (kcnt != NULL)
  1374.     *kcnt = cnt;
  1375.     return (mlen);
  1376. }
  1377.  
  1378.  
  1379. /* calculate the number and max-width of the keys for an splot.
  1380.  * Note that a blank line is issued after each set of contours
  1381.  */
  1382. int find_maxl_keys3d(plots, count, kcnt)
  1383. struct surface_points *plots;
  1384. int count, *kcnt;
  1385. {
  1386.     int mlen, len, surf, cnt;
  1387.     struct surface_points *this_plot;
  1388.  
  1389.     mlen = cnt = 0;
  1390.     this_plot = plots;
  1391.     for (surf = 0; surf < count; this_plot = this_plot->next_sp, surf++) {
  1392.  
  1393.     /* we draw a main entry if there is one, and we are
  1394.      * drawing either surface, or unlabelled contours
  1395.      */
  1396.     if (this_plot->title && *this_plot->title &&
  1397.         (draw_surface || (draw_contour && !label_contours))) {
  1398.         ++cnt;
  1399.         len = strlen(this_plot->title);
  1400.         if (len > mlen)
  1401.         mlen = len;
  1402.     }
  1403.     if (draw_contour && label_contours && this_plot->contours != NULL) {
  1404.         len = find_maxl_cntr(this_plot->contours, &cnt);
  1405.         if (len > mlen)
  1406.         mlen = len;
  1407.     }
  1408.     }
  1409.  
  1410.     if (kcnt != NULL)
  1411.     *kcnt = cnt;
  1412.     return (mlen);
  1413. }
  1414.  
  1415. static int find_maxl_cntr(contours, count)
  1416. struct gnuplot_contours *contours;
  1417. int *count;
  1418. {
  1419.     register int cnt;
  1420.     register int mlen, len;
  1421.     register struct gnuplot_contours *cntrs = contours;
  1422.  
  1423.     mlen = cnt = 0;
  1424.     while (cntrs) {
  1425.     if (label_contours && cntrs->isNewLevel) {
  1426.         len = strlen(cntrs->label);
  1427.         if (len)
  1428.         cnt++;
  1429.         if (len > mlen)
  1430.         mlen = len;
  1431.     }
  1432.     cntrs = cntrs->next;
  1433.     }
  1434.     *count += cnt;
  1435.     return (mlen);
  1436. }
  1437.  
  1438. static void save_range(fp, axis, min, max, autosc, text)
  1439. FILE *fp;
  1440. int axis;
  1441. double min, max;
  1442. TBOOLEAN autosc;
  1443. char *text;
  1444. {
  1445.     int i;
  1446.  
  1447.     i = axis;
  1448.     fprintf(fp, "set %srange [ ", text);
  1449.     if (autosc & 1) {
  1450.     putc('*', fp);
  1451.     } else {
  1452.     SAVE_NUM_OR_TIME(fp, min, axis);
  1453.     }
  1454.     fputs(" : ", fp);
  1455.     if (autosc & 2) {
  1456.     putc('*', fp);
  1457.     } else {
  1458.     SAVE_NUM_OR_TIME(fp, max, axis);
  1459.     }
  1460.  
  1461.     fprintf(fp, " ] %sreverse %swriteback",
  1462.         range_flags[axis] & RANGE_REVERSE ? "" : "no",
  1463.         range_flags[axis] & RANGE_WRITEBACK ? "" : "no");
  1464.  
  1465.     if (autosc) {
  1466.     /* add current (hidden) range as comments */
  1467.     fputs("  # (currently [", fp);
  1468.     if (autosc & 1) {
  1469.         SAVE_NUM_OR_TIME(fp, min, axis);
  1470.     }
  1471.     putc(':', fp);
  1472.     if (autosc & 2) {
  1473.         SAVE_NUM_OR_TIME(fp, max, axis);
  1474.     }
  1475.     fputs("] )", fp);
  1476.     }
  1477.     putc('\n', fp);
  1478. }
  1479.  
  1480. /* check user defined format strings for valid double conversions */
  1481. TBOOLEAN valid_format(format)
  1482. const char *format;
  1483. {
  1484.     for (;;) {
  1485.     if (!(format = strchr(format, '%')))    /* look for format spec  */
  1486.         return TRUE;    /* passed Test           */
  1487.     do {            /* scan format statement */
  1488.         format++;
  1489.     } while (strchr("+-#0123456789.", *format));
  1490.  
  1491.     switch (*format) {    /* Now at format modifier */
  1492.     case '*':        /* Ignore '*' statements */
  1493.     case '%':        /* Char   '%' itself     */
  1494.         format++;
  1495.         continue;
  1496.     case 'l':        /* Now we found it !!! */
  1497.         if (!strchr("fFeEgG", format[1]))    /* looking for a valid format */
  1498.         return FALSE;
  1499.         format++;
  1500.         break;
  1501.     default:
  1502.         return FALSE;
  1503.     }
  1504.     }
  1505. }
  1506.